<?php

declare(strict_types=1);

/**
 * @Author:     Frank
 * @contact     frank_hhm@163.com
 * @Date:       2023-02-06 21:31:16
 * @Last Modified time: 2023-02-13 20:12:11
 */

namespace app\common\factory\store\goods\source;

use app\common\services\store\GoodsService;
use app\common\services\store\GoodsSkuService;
use think\facade\Db;
/**
 * 商品来源-普通商品扩展类
 * Class Master
 * @package app\common\factory\store\goods\source
 */
class Master extends Base
{

    /**
     * 更新商品库存 (针对下单减库存的商品)
     */
    public function updateGoodsStock($goodsList)
    {
        $data = [];
        foreach ($goodsList as $goods) {
            // 下单减库存
            if ( $goods['deduct_stock_type'] == 2 ) {
                $data[] = [
                    'total' => $goods['total_num'],
                    'data' => ['stock' => ['dec',  $goods['total_num']]],
                    'where' => [
                        'goods_id' => $goods['id'],
                        'id' => $goods['goods_sku_id'],
                    ],
                ];
            }
        }
        return (!empty($data) && $this->updateGoodsSku($data)) || true;
    }

    /**
     * 更新商品库存销量（订单付款后）
     */
    public function updateStockSales($goodsList)
    {
        $goodsData = [];
        $goodsSkuData = [];
        foreach ($goodsList as $goods) {
            // 记录商品的销量
            $goodsData[] = [
                'data' => [
                    'sales_actual' => Db::raw('sales_actual+'. $goods['total_num'])
                ],
                'where' => ['id' => $goods['goods_id']]
            ];
            $data['goods_sales'] =  Db::raw('goods_sales+'. $goods['total_num']);

            $where = [
                'goods_id' => $goods['goods_id'],
                'id' => $goods['goods_sku_id'],
            ];
            // 付款减库存
            if ($goods['deduct_stock_type'] == 1) {
                $data['stock'] =  Db::raw('stock-'. $goods['total_num']);
            }
            $goodsSkuData[] = [
                'total' => $goods['total_num'],
                'data' => $data,
                'where' => $where
            ];
        }
        // 更新商品销量
        $status = !empty($goodsData) && $this->updateGoods($goodsData);
        // 更新商品sku库存
        return ($status && !empty($goodsSkuData) && $this->updateGoodsSku($goodsSkuData)) || true;
    }


    /**
     * 回退商品库存
     */
    public function backGoodsStock($goodsList, $sourceId = 0, $isPayOrder = false)
    {
        $goodsSkuData = [];
        foreach ($goodsList as $goods) {
            $item = [
                'where' => [
                    'goods_id' => $goods['goods_id'],
                    'id' => $goods['goods_sku_id'],
                ],
                'data' => [
                    'stock' => Db::raw('stock+'. $goods['total_num'])
                ],
            ];
            if ($isPayOrder == true) {
                // 付款订单全部库存
                $goodsSkuData[] = $item;
            }
        }
        // 更新商品sku库存
        return true || (!empty($goodsSkuData) && $this->updateGoodsSku($goodsSkuData));
    }

    /**
     * 更新商品信息
     */
    private function updateGoods($data)
    {
        $service = GoodsService::instance();
        foreach ($data as $item) {
            $service->update($item['where'],$item['data']);
        }
        return true;
    }

    /**
     * 更新商品sku信息
     */
    private function updateGoodsSku($data)
    {
        $status = true;
        foreach ($data as $item) {
            if(!$status = $this->updateGoodsSkuLock($item)){
                continue;
            }
        }
        return $status;
    }

    /**
     * 开启加锁
     */
    private function updateGoodsSkuLock($param){
        $service = GoodsSkuService::instance();
        $sku = $service->search($param['where'])->lock(true)->find();
        if (empty($sku)) {
            $this->error = '很抱歉，商品库存不存在';
            return false;
        }
        if ($sku['stock'] < $param['total']) {
            $this->error = '很抱歉，商品库存不足';
            return false;
        }
        return $service->update($param['where'],$param['data']);
        
    }
}